import 'dart:convert';
import 'dart:typed_data';
import 'package:bip39/src/wordlists/english.dart' as bip39_words; // 直接导入词表文件
import 'package:crypto/crypto.dart'; // 用于 SHA256
import 'package:test/test.dart';

/// BIP39 助记词生成工具类
class BIP39Converter {

  static List<String> englishWordlist = bip39_words.WORDLIST; // 正确访问词表
  /// 将 secp256k1 私钥转换为 BIP39 助记词
  static List privateKeyToMnemonic(Uint8List privateKey) {
    // 验证私钥长度必须为 32 字节
    if (privateKey.length != 32) {
      throw ArgumentError('Invalid secp256k1 private key length');
    }

    // 1. 计算校验和 (SHA256 的第一个字节)
    final checksumByte = sha256.convert(privateKey).bytes[0];

    // 2. 将私钥（熵）和校验和转换为二进制位列表
    final entropyBits = _bytesToBits(privateKey);
    final checksumBits = _byteToBits(checksumByte, 8).sublist(0, 8); // 取前 8 位

    // 3. 组合熵 + 校验位（总长度 = 256 + 8 = 264 bits）
    final combinedBits = entropyBits + checksumBits;

    // 4. 将 264 bits 分割为 24 组 11-bit 的索引
    final indices = _bitsToIndices(combinedBits, 11);

    // 5. 映射到英文词表
    return indices.map((index) => englishWordlist[index]).toList();
  }

  // -- 私有工具函数 --

  /// 将字节数组转换为二进制位列表（每个字节转为 8 bits）
  static List<int> _bytesToBits(Uint8List bytes) {
    return bytes.expand((byte) => _byteToBits(byte, 8)).toList();
  }

  /// 将单个字节转换为二进制位列表
  static List<int> _byteToBits(int byte, int bitLength) {
    return List.generate(bitLength, (i) => (byte >> (bitLength - 1 - i)) & 1);
  }

  /// 将二进制位列表分割为指定长度的整数索引
  static List<int> _bitsToIndices(List<int> bits, int bitsPerIndex) {
    final indices = <int>[];
    for (int i = 0; i < bits.length; i += bitsPerIndex) {
      int index = 0;
      for (int j = 0; j < bitsPerIndex; j++) {
        index = (index << 1) | bits[i + j];
      }
      indices.add(index);
    }
    return indices;
  }
}

/// ----------------- 测试用例 -----------------


void main() {
  // 测试向量：私钥全 0x00...01
  test('私钥转助记词', () {
    final privateKey = Uint8List.fromList(List.filled(32, 0)..[31] = 1);
    final mnemonic = BIP39Converter.privateKeyToMnemonic(privateKey);

    expect(mnemonic, [
      'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'abandon',
      'abandon', 'abandon', 'abandon', 'abandon', 'abandon', 'about'
    ]);
  });

  // 异常测试：私钥长度错误
  test('异常处理 - 无效私钥长度', () {
    expect(
          () => BIP39Converter.privateKeyToMnemonic(Uint8List(31)),
      throwsA(isA<ArgumentError>()),
    );
  });
}